package com.xinbochuang.machine.admin.controller.api;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.DynamicParameter;
import com.github.xiaoymin.knife4j.annotations.DynamicResponseParameters;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
import com.xinbochuang.machine.admin.domain.plan.CheckPlan;
import com.xinbochuang.machine.admin.domain.system.SysDept;
import com.xinbochuang.machine.admin.domain.system.SysUser;
import com.xinbochuang.machine.admin.dto.TokenRequestBean;
import com.xinbochuang.machine.admin.service.plan.ICheckPlanService;
import com.xinbochuang.machine.admin.service.system.ISysDeptService;
import com.xinbochuang.machine.admin.service.system.ISysUserService;
import com.xinbochuang.machine.admin.utils.MD5Util;
import com.xinbochuang.machine.common.constant.Constants;
import com.xinbochuang.machine.common.domain.LoginUser;
import com.xinbochuang.machine.common.domain.TableDataInfo;
import com.xinbochuang.machine.common.exception.CustomException;
import com.xinbochuang.machine.common.exception.user.CaptchaException;
import com.xinbochuang.machine.common.exception.user.CaptchaExpireException;
import com.xinbochuang.machine.common.exception.user.UserPasswordNotMatchException;
import com.xinbochuang.machine.common.redis.RedisCache;
import com.xinbochuang.machine.common.utils.*;
import com.xinbochuang.machine.framework.security.custom.IdCardAuthenticationToken;
import com.xinbochuang.machine.framework.web.domain.AjaxResult;
import com.xinbochuang.machine.framework.web.service.SysLoginService;
import com.xinbochuang.machine.framework.web.service.TokenService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.http.Header;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * app用户登陆接口
 *
 * @author 黄晓鹏
 * @date 2020-09-13 17:51
 */
@Api(value = "app登陆接口", position = 100, protocols = "http")
@Validated
@RestController
@RequestMapping("/api")
public class AppLoginController {

    @Resource
    private SysLoginService loginService;

    @Resource
    private ISysDeptService deptService;

    @Resource
    private AuthenticationManager authenticationManager;

    @Resource
    private RedisCache redisCache;
    @Resource
    private ISysUserService iSysUserService;
    @Resource
    private UserDetailsService userDetailsService;
    @Resource
    private TokenService tokenService;

    @Resource
    private ICheckPlanService checkPlanService;

    @Resource
    private ISysUserService userService;
    /**
     * app登录方法
     *
     * @param idCard 身份证
     * @return 结果
     */
    @ApiOperation(value = "通过身份证号登陆", consumes = "application/json", response = AjaxResult.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "身份证号", name = "idCard", required = true),
    })
    @ApiOperationSupport(
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "状态码", name = "code", dataTypeClass = int.class, example = "200"),
                    @DynamicParameter(value = "是否成功", name = "status", dataTypeClass = boolean.class, example = "true"),
                    @DynamicParameter(value = "返回消息", name = "msg", example = "操作成功"),
                    @DynamicParameter(value = "token", name = "token"),
                    @DynamicParameter(value = "data", name = "data"),
            })
    )
    @GetMapping("/applogin")
    public AjaxResult login(@NotNull(message = "身份证号不能空！")String idCard) {
        idCard=AESUtils.decode(idCard);
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper=new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getIdCard,idCard).eq(SysUser::getStatus,"4").eq(SysUser::getDelFlag,"0");
        List<SysUser> list = iSysUserService.list(sysUserLambdaQueryWrapper);
        if(list.isEmpty()){
            throw new CustomException("用户不存在，请先采集信息");
        }
        SysUser sysUser = list.get(0);

        AjaxResult json = AjaxResult.ok();
        LoginUser loginUser = (LoginUser)userDetailsService.loadUserByUsername(sysUser.getUsername());
        loginUser.getUser().setPassword("");
        // 生成token

        String token = tokenService.createToken(loginUser);
        json.put(Constants.TOKEN, token);
        json.put(Constants.DATA, AESUtils.encode( JSON.toJSONStringWithDateFormat(loginUser.getUser(),"yyyy-MM-dd HH:mm:ss")));
        return json;
    }
    @GetMapping("/getDeptListTree")
    public AjaxResult getDeptListTree() {
        SysDept dept = new SysDept();
        List<SysDept> deptList = deptService.selectDeptList(dept);
        return AjaxResult.data(AESUtils.encode( JSON.toJSONStringWithDateFormat(deptService.buildDeptTreeSelect(deptList),"yyyy-MM-dd HH:mm:ss")));
    }


    /**
     * app登录方法
     *
     * @param username 身份证
     * @return 结果
     */
    @ApiOperation(value = "通过身份证号登陆", consumes = "application/json", response = AjaxResult.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "手机号", name = "username", required = true),
            @ApiImplicitParam(value = "密码", name = "password", required = true),
    })
    @ApiOperationSupport(
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "状态码", name = "code", dataTypeClass = int.class, example = "200"),
                    @DynamicParameter(value = "是否成功", name = "status", dataTypeClass = boolean.class, example = "true"),
                    @DynamicParameter(value = "返回消息", name = "msg", example = "操作成功"),
                    @DynamicParameter(value = "token", name = "token"),
                    @DynamicParameter(value = "data", name = "data"),
            })
    )
    @GetMapping("/lgByPassword")
    public AjaxResult loginByPassword(String username, String password) {
        if(StringUtils.isEmpty(username)){

            return AjaxResult.error(-1,"用户名不允许为空！");
        }
        if(StringUtils.isEmpty(password)){

            return AjaxResult.error(-1,"密码不允许为空");
        }
        username=AESUtils.decode(username);
        password=AESUtils.decode(password);
        LoginUser loginUser = (LoginUser)userDetailsService.loadUserByUsername(username);
        if(loginUser==null) {
            return AjaxResult.error(-1,"用户不存在！");
        }
        boolean b = SecurityUtils.matchesPassword(password, loginUser.getUser().getPassword());
        if(!b){
            return AjaxResult.error(-1,"密码错误！");
        }

        AjaxResult json = AjaxResult.ok();
        loginUser.getUser().setPassword("");
        // 生成token

        String token = tokenService.createToken(loginUser);
        json.put(Constants.TOKEN, token);
        json.put(Constants.DATA, AESUtils.encode(JSON.toJSONStringWithDateFormat(loginUser.getUser(),"yyyy-MM-dd HH:mm:ss")));
        return json;
    }
    @ApiOperation(value = "获取短信验证码", consumes = "application/json", response = AjaxResult.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "手机号", name = "phone", required = true),
    })
    @GetMapping("/sendValidateCode")
    public AjaxResult sendValidateCode(String phone){
        if(StringUtils.isEmpty(phone)){

            return AjaxResult.error(-1,"手机号不允许为空！");
        }
        phone=AESUtils.decode(phone);
        if(!CommonUtils.isPhonenumber(phone)){
            return AjaxResult.error(-1,"手机号码不正确！");
        }
        Object object = redisCache.getCacheObject("validateCode:_"+phone);
        if (object != null) {
            return AjaxResult.error(-1,"验证码5分钟内，仍然有效！");
        }
        String verifyCode = String
                .valueOf((int) ((Math.random() * 9 + 1) * 100000));
        redisCache.setCacheObject("validateCode:_"+phone, verifyCode, 5, TimeUnit.MINUTES);
        MessageUtils.sendValidateCode(phone,verifyCode);
        return AjaxResult.ok("短信验证码已发送成功");
    }

    /**
     * app登录方法
     *
     * @return 结果
     */
    @ApiOperation(value = "通过身份证号登陆", consumes = "application/json", response = AjaxResult.class)
    @ApiImplicitParams({
            @ApiImplicitParam(value = "手机号", name = "phone", required = true),
            @ApiImplicitParam(value = "短信验证码", name = "validateCode", required = true),
    })
    @ApiOperationSupport(
            responses = @DynamicResponseParameters(properties = {
                    @DynamicParameter(value = "状态码", name = "code", dataTypeClass = int.class, example = "200"),
                    @DynamicParameter(value = "是否成功", name = "status", dataTypeClass = boolean.class, example = "true"),
                    @DynamicParameter(value = "返回消息", name = "msg", example = "操作成功"),
                    @DynamicParameter(value = "token", name = "token"),
                    @DynamicParameter(value = "data", name = "data"),
            })
    )
    @GetMapping("/loginByPhone")
    public AjaxResult loginByPhone(String phone, String validateCode) {
        phone=AESUtils.decode(phone);
        String oldCode = redisCache.getCacheObject("validateCode:_"+phone);
        if(StringUtils.isBlank(oldCode)){
            throw new CustomException("验证码已失效，请重新获取！");
        }
        if(!oldCode.equals(validateCode)){
            throw new CustomException("验证码错误，请重新输入！");
        }
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper=new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getPhone,phone).eq(SysUser::getStatus,"4").eq(SysUser::getDelFlag,"0");
        List<SysUser> list = iSysUserService.list(sysUserLambdaQueryWrapper);
        if(list.isEmpty()){
            throw new CustomException("用户不存在，请先采集信息");
        }
        SysUser sysUser = list.get(0);

        AjaxResult json = AjaxResult.ok();
        LoginUser loginUser = (LoginUser)userDetailsService.loadUserByUsername(sysUser.getUsername());
        loginUser.getUser().setPassword("");
        // 生成token

        String token = tokenService.createToken(loginUser);
        json.put(Constants.TOKEN, token);
        json.put(Constants.DATA, AESUtils.encode(JSON.toJSONStringWithDateFormat(loginUser.getUser(),"yyyy-MM-dd HH:mm:ss")));
        return json;
    }



    @PostMapping("/verifyToken")
    public AjaxResult verifyToken(@RequestBody TokenRequestBean tokenRequestBean){
        String token=tokenRequestBean.getToken();
        String clientId = "bit_sanfang_zhjf";
        String secretToken = "bf3dfe7127dc4249";
        String clientIdMD5 = MD5Util.encrypt(clientId);
        String secretKeyMD5 = MD5Util.encrypt(secretToken);
        Long timestamp = System.currentTimeMillis();
        String authCode = MD5Util.encrypt(clientIdMD5 + secretKeyMD5);
        String signature = Hashing.sha256().newHasher().putString(timestamp+ secretToken + authCode, Charsets.UTF_8).hash().toString();

        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("client_id", clientId);
        jsonObject1.put("token", token);
        jsonObject1.put("signature",signature);
        jsonObject1.put("timestamp",timestamp+"");
        String post = HttpUtils.post("http://10.229.182.153:8000/bit-msa-sso/security/v1/oauth/verify", JSONObject.toJSONString(jsonObject1),token);
        System.out.println("===post==="+post+"   params:"+JSONObject.toJSONString(jsonObject1));
        JSONObject result1 = JSONObject.parseObject(post);
        if(result1.getInteger("code")==1000){
            String account=result1.getJSONObject("data").getString("account");
            String userResultStr = HttpUtils.get("http://10.229.182.153:8000/ultra-uc-core/user/info/main/"+account,token);
            System.out.println("===userResultStr==="+userResultStr);
            JSONObject result2 = JSONObject.parseObject(userResultStr);
            if(result2.getInteger("code")==200){
                String account1=result2.getJSONObject("data").getString("account");
                String name=result2.getJSONObject("data").getString("name");
                String mobile=result2.getJSONObject("data").getString("mobile");
                String orgText=result2.getJSONObject("data").getString("orgText");
                LoginUser loginUser=null;
                try {
                    loginUser = (LoginUser) userDetailsService.loadUserByUsername(account1);
                }catch (Exception e){

                }
                if(loginUser==null) {
                    SysDept dept = new SysDept();
                    dept.setDeptName(orgText);
                    List<SysDept> deptList = deptService.selectDeptList(dept);
                    if(deptList.isEmpty()||deptList.size()>1){
                        return AjaxResult.error(-1,"人员归属部门无法关联，请联系管理员！");
                    }
                    SysUser sysUser=new SysUser();
                    sysUser.setUsername(account);
                    sysUser.setNickname(name);
                    sysUser.setPhone(mobile);
                    sysUser.setDeptId(deptList.get(0).getDeptId());
                    sysUser.setDelFlag("0");
                    sysUser.setStatus("4");
                    sysUser.setIsWhite("1");
                    sysUser.setCreateTime(DateUtils.dateTimeNow());
                    userService.insertUser(sysUser);
                    loginUser = (LoginUser)userDetailsService.loadUserByUsername(account1);
                    String tokenN = tokenService.createToken(loginUser);
                    AjaxResult json = AjaxResult.ok();
                    json.put(Constants.TOKEN, tokenN);
                    json.put(Constants.DATA, AESUtils.encode(JSON.toJSONStringWithDateFormat(loginUser.getUser(),"yyyy-MM-dd HH:mm:ss")));
                    return json;
                }else{
                    String tokenN = tokenService.createToken(loginUser);
                    AjaxResult json = AjaxResult.ok();
                    json.put(Constants.TOKEN, tokenN);
                    json.put(Constants.DATA, AESUtils.encode(JSON.toJSONStringWithDateFormat(loginUser.getUser(),"yyyy-MM-dd HH:mm:ss")));
                    return json;
                }
            }else{
                return AjaxResult.error(-1,"获取用户失败，请联系管理员！");
            }
        }else{
            return AjaxResult.error(-1,"鉴权失败，请联系管理员！");
        }
    }
}
